#include "Fat32.h"
#include "sdcard.h"
#include <string.h>

extern u32 SD_Buffer[128];
//初始化FAT32,获取结构体信息
FAT_ERROR FAT32_Init(FAT32_MBR* MBR_Info, FAT32_Volume* Volume, fat32_file* File)
{
	SD1.ERRORid = SD_ReadBlock(&SD1, SD_Buffer, 0, 512);
	if(SD1.ERRORid != SD_OK)
	{
		return SD_failed;
	}
	FAT_ERROR FAT_errorinfo =FAT32_MBR_Init((u8*)SD_Buffer, MBR_Info);//FAT错误信息
	if(FAT_errorinfo != FAT_OK)
	{
		return FAT_errorinfo;
	}
	Volume->MBR = MBR_Info;
	if(MBR_Info->StartSector != 0)
	{
		SD1.ERRORid = SD_ReadBlock(&SD1, SD_Buffer,MBR_Info->StartSector, 512);//FAT32引导扇区
		if(SD1.ERRORid != SD_OK)
		{
			return SD_failed;
		}
	}
	//读取卷信息
	FAT_errorinfo = FAT32_Volume_Init((u8*)SD_Buffer, MBR_Info, Volume);
	File->Volume = Volume;
	
	return FAT_errorinfo;
	
}

//MBR信息获取，Buffer是硬盘的第0个扇区，如果MBR不存在返回1
//如果FAT不存在，MBR存在返回2
FAT_ERROR FAT32_MBR_Init(u8* Buffer, FAT32_MBR* MBR_Info)
{
    if((((u32*)Buffer)[0] & 0xFFFFFF) == 0x8EC033)
    //如果有MBR分区表
    {
        for (u8 i = 0; i < 4; i++)
        {
            MBR_Info->FSysType = Buffer[DPT_ADDR + 0x10*i + 4];
            if(MBR_Info->FSysType == 0x0C || MBR_Info->FSysType == 0x0B)
            //如果这个分区时FAT32文件系统
            {
                MBR_Info->ParState = Buffer[DPT_ADDR + 0x10*i];
                MBR_Info->StartSector = *(u32*)(Buffer + DPT_ADDR + 0x10*i + 8);
                MBR_Info->OccupiedSector = *(u32*)(Buffer + DPT_ADDR + 0x10*i + 12);
                return FAT_OK;//找到第一个FAT32卷
            }//DPT表
            else
            {
                continue;
            } 
        }  
        //有MBR但是没有FAT32文件系统
        MBR_Info->OccupiedSector = 0;
        MBR_Info->FSysType = 0;
        MBR_Info->StartSector = 0;
        return FAT32_NOTFOUND;
    }
    else
    {
        MBR_Info->StartSector = 0;
        return MBR_NOTFOUND;
    }
       
}
//通过BPB扇区读取卷信息
FAT_ERROR FAT32_Volume_Init(u8* Buffer, FAT32_MBR* MBR, FAT32_Volume* Volume)
{
    Volume->FATSector = *(u16*)(Buffer + RESERVEDSECTORNUM_ADDR);
    Volume->FATSizeOfSector = *(u32*)(Buffer + FATSECTORNUM_ADDR);
    Volume->FATNum = Buffer[FATNUM_ADDR];
    Volume->SectorSize = *(u16*)(Buffer + SECTORSIZE_ADDR);
    Volume->ClusterSizeOfSector = Buffer[CLUSTERSIZE_ADDR];
    Volume->Sector_Root = Volume->FATSector + Volume->FATNum*Volume->FATSizeOfSector;
    Volume->MBR = MBR;
		
    return FAT_OK;
}

//找到文件的位置,Buffer目录的一个扇区
FAT_ERROR fat32_findExt(fat32_file* file, const char* extname)
{
	strcpy(file->fext,"\0");
	strcpy(file->fname,"\0");
	file->file_dir = 0;
	
	do{
		SD1.ERRORid = SD_ReadBlock(&SD1,(u8*)SD_Buffer,FAT32_GetDirSector(file),512);
		if(SD1.ERRORid != SD_OK)
		{
			return SD_failed;
		}
		do
		{
			FAT32_DirStruct* Dir = (FAT32_DirStruct*)((u8*)SD_Buffer + file->file_dir * Dir1Size);//当前目录项
			if (*(u8*)Dir == 0x00)//如果遇到空目录项，需要重置。
			{
				file->pDir_Sector = 0;
				file->file_dir = 0;
				return scan_over;
			}
			if (Dir->ExpandName[0] == extname[0] &&\
					Dir->ExpandName[1] == extname[1] &&\
					Dir->ExpandName[2] == extname[2])
			{
					//找到文件，拷贝信息。
					file->startCluster = Dir->Cluster_H16<<16 | Dir->Cluster_L16;
					file->pCluster = file->startCluster;
					file->pSector = 0;
					return FileFound;
			}
			file->file_dir++;
		}while(file->file_dir < (file->Volume->SectorSize >> 5));
		file->pDir_Sector++;
		file->file_dir = 0;
	}while(1);
	
	return Notfound;
}


//通过文件信息读取文件内容512B。存在Buffer中。
FAT_ERROR fat32_fread(fat32_file* File, void* Buffer)
{
	u32 FAT_buffer[128];
  SD1.ERRORid = SD_ReadBlock(&SD1, Buffer, FAT32_getFileClusterSector(File) + File->pSector, 512);
	if(SD1.ERRORid != SD_OK)
	{
		return SD_failed;
	}
  File->pSector++;
	if(File->pSector >= File->Volume->ClusterSizeOfSector)
		//如果超出簇的大小
	{
		File->pSector = 0;
		SD1.ERRORid = SD_ReadBlock(&SD1, FAT_buffer, FAT32_getFileFATSector(File), 512);
		if(SD1.ERRORid != SD_OK)
		{
			return SD_failed;
		}
		//根据FAT数据，找到簇链的下一个簇号。
		File->pCluster = FAT_buffer[File->pCluster % (File->Volume->SectorSize >> 2)];
		if(File->pCluster == 0x0FFFFFFF)
			return File_End;
	}
	return FAT_OK;
}

void fat32_file_init(fat32_file* file)
{
	memset(file, 0, sizeof(fat32_file)-sizeof(u32));
}

FAT_ERROR fat32_fnew(fat32_file* file, const char* fname, FAT32_Volume* volume, u32* fat_buf)//新建文件
{
	fat32_file_init(file);
	strcpy(file->fname, fname);
	strcpy(file->fext, "PCM");
	file->Volume = volume;
	u8 use_e5 = 0;//是否使用e5目录项
	do
	{//找空目录，未使用目录项
		SD1.ERRORid = SD_ReadBlock(&SD1, SD_Buffer, FAT32_GetDirSector(file), 512);
		if(SD1.ERRORid != SD_OK)
		{
			return SD_failed;
		}
		do
		{
			FAT32_DirStruct* Dir = (FAT32_DirStruct*)((u8*)SD_Buffer + file->file_dir * Dir1Size);//当前目录项
			if(*(u8*)Dir == 0x00 ||(*(u8*)Dir == 0xE5 && use_e5))
				//找到空目录项
			{
				if(FAT_Fulled == fat32_Clusteralloc(file, fat_buf))//分配空闲簇
					return FAT_Fulled;//簇满
				
//				Dir->attribute = 0x00;
//				Dir->Cluster_H16 = (file->pCluster >> 4);
//				Dir->Cluster_L16 = file->pCluster & 0xFFFF;
//				strcpy(Dir->FileName, file->fname);
//				strcpy(Dir->ExpandName, file->fext);
//				SD1.ERRORid = SD_WriteBlock(&SD1, SD_Buffer, FAT32_GetDirSector(file), 512);
			}
			file->file_dir++;
		}while(file->file_dir < (file->Volume->SectorSize >> 5));
		file->pDir_Sector++;
	}while(1);
}

//在FAT表中，从当前簇开始找一个空闲的簇
//返回簇号
FAT_ERROR fat32_Clusteralloc(fat32_file* file, u32* fat_buf)
{
	u32 fat_sector = FAT32_getFileFATSector(file);//当前FAT扇区
	u32 offset_sector = fat_sector - file->Volume->FATSector;//FAT偏移扇区
	const u16 fat_addr = file->pCluster % (file->Volume->SectorSize>>2);//扇区内偏移地址
	if(file->pCluster == 0)
	{//如果是新文件
		SD1.ERRORid = SD_ReadBlock(&SD1, fat_buf, fat_sector,512);
		if(SD1.ERRORid != SD_OK)
		{
			return SD_failed;
		}
	}
	else
	{
	//在fat_buf里寻找空闲簇
		for(int i = fat_addr;i < 128;i++)
		{	
			if(fat_buf[i] == 0)
			{//找到了空闲簇
				fat_buf[fat_addr] = i + offset_sector*128;
				file->pCluster = fat_buf[fat_addr];
				return FAT_OK;
			}
		}
		//没找到
		for(int i = 0; (fat_sector + i) < file->Volume->FATSizeOfSector; i++)
		{//在新的fat表查找。
			SD1.ERRORid = SD_ReadBlock(&SD1, SD_Buffer, fat_sector + i, 512);
			if(SD1.ERRORid != SD_OK)
			{
				return SD_failed;
			}
			for(int i = 0;i<(file->Volume->SectorSize>>2);i++)
			{
				if(((u32*)SD_Buffer)[i] == 0)
				{//找到了
					file->pCluster = fat_sector*(file->Volume->SectorSize>>2) + i;
					fat_buf[fat_addr] = file->pCluster;
					//写入fat表
					SD1.ERRORid = SD_WriteBlock(&SD1, fat_buf, fat_sector, 512);
					if(SD1.ERRORid != SD_OK)
					{
						return SD_failed;
					}
				}
			}
		}
		return FAT_Fulled;
	}
}

FAT_ERROR fat32_fwrite(fat32_file* file, void* buf, u32* FAT_Buf)//写入文件
{
	SD1.ERRORid = SD_WriteBlock(&SD1, buf, FAT32_getFileClusterSector(file) + file->pSector, 512);
	if(SD1.ERRORid != SD_OK)
	{
		return SD_failed;
	}
	file->pSector++;
	if(file->pSector >= file->Volume->ClusterSizeOfSector)
	{
		fat32_Clusteralloc(file, FAT_Buf);
	}
	return FAT_OK;
}	
//关闭文件写入操作，向FAT_buf的当前簇链对象写入文件终止号0x0FFFFFFF，并写入sd卡的fat表中
FAT_ERROR fat32_fclose(fat32_file* file, u32* fat_buf)
{
	u32 fat_addr = file->pCluster % (file->Volume->SectorSize>>2);
	fat_buf[fat_addr] = 0x0FFFFFFF;
	SD1.ERRORid = SD_WriteBlock(&SD1, fat_buf, FAT32_getFileFATSector(file), 512);
	if(SD1.ERRORid != SD_OK)
	{
		return SD_failed;
	}
	return FAT_OK;
}

